#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QDebug>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QTimer>
#include <QString>
#include "qcustomplot.h"
#include <realtimedatawidget.h>
#include "form.h"
#include "ui_form.h"
#include "parsedDataWindow.h"
#include <QtUiTools/QUiLoader>
#include <QFile>
#include "SendMessageThread.h"
#include <QSerialPort>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , receivedData(""),
    dataWidget_AD(nullptr),
    dataWidget_DTV(nullptr),
    dataWidget_Pi(nullptr)
{
    ui->setupUi(this);
    setWindowTitle("串口调试助手");
    // 设置窗口图标
    QIcon icon(":image/favicon.ico"); // 使用资源文件中的图标
    setWindowIcon(icon);
    //设置窗口大小
    resize(1500, 700); // 设置窗口大小为宽800像素，高600像素
    //设置中心部件
    //setCentralWidget(ui->textEdit);

    connect(ui->pushButton_plot, &QPushButton::clicked, this, &MainWindow::showForm);


    // 关闭TextEdit的自动回车功能
    ui->textEdit->setWordWrapMode(QTextOption::NoWrap);
    ui->textEdit->setLineWrapMode(QTextEdit::NoWrap);
    ui->textEdit_2->setWordWrapMode(QTextOption::NoWrap);
    ui->textEdit_2->setLineWrapMode(QTextEdit::NoWrap);

    // 获取可用串口列表并添加到下拉列表框
    foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
    {
        QSerialPort serial;
        QSerialPortInfo qinfo;
        serial.setPort(info);
        if(serial.open(QIODevice::ReadWrite))
        {
            ui->comboBox_PortName->addItem(serial.portName());
            serial.close();
        }

    }
    // 在窗体初始化或者构造函数中设置comboBox_PortName的初始选择
    ui->comboBox_PortName->setCurrentText("COM2");

    // 获取系统支持的波特率列表
    QList<qint32> baudRates = QSerialPortInfo::standardBaudRates();

    // 遍历每个波特率并添加到ComboBox中
    foreach(qint32 baudRate, baudRates) {
        ui->comboBox_Boud->addItem(QString::number(baudRate));
    }

    connect(ui->comboBox_Boud,static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, [=](){
        QString string_com=ui->comboBox_Boud->currentText();
        qDebug() << "Boud is:"<<string_com;
    });
    //默认串口
    ui->comboBox_Boud->setCurrentText("9600");


    // 创建串口对象
    QSerialPort * serial = new QSerialPort;

    // 配置串口参数
    connect(ui->open,&QPushButton::clicked,this, [=](){

        QString string_com = ui->comboBox_PortName->currentText();
        qint32 baudRate =ui->comboBox_Boud->currentText().toInt();

        // 配置串口参数
        serial->setPortName(string_com); // 设置串口名称
        serial->setBaudRate(baudRate); // 设置波特率

        serial->setDataBits(QSerialPort::Data8); // 设置数据位
        serial->setParity(QSerialPort::NoParity); // 设置奇偶校验位
        serial->setStopBits(QSerialPort::OneStop); // 设置停止位
        serial->setFlowControl(QSerialPort::NoFlowControl); // 设置流控制

        qDebug() << "com is:"<<string_com;
        qDebug() << "baudRate is:"<<baudRate;
        // 打开串口
        if (serial->open(QIODevice::ReadWrite)) {
            qDebug() << "Serial port opened！\r\n";
            ui->textEdit_2 -> append("Serial port opened successfully！\r");
            // 在添加新文本后，确保 QTextEdit 自动滚动到最后
            ui->textEdit_2->ensureCursorVisible();


        } else {
            qDebug() << "Failed to open serial port!";
            ui->textEdit_2 -> append("Failed to open serial port!\r");
            // 在添加新文本后，确保 QTextEdit 自动滚动到最后
            ui->textEdit_2->ensureCursorVisible();
        }
    }
            );

    // 设置串口的读写缓冲区大小为 4096 字节
    serial->setReadBufferSize(4096);


    //关闭串口
    connect(ui->close,&QPushButton::clicked,this, [=](){
        serial->close();
        qDebug() << "Serial port Close！\r\n";
        ui->textEdit_2 -> append("Serial port Close！\r");
        // 在添加新文本后，确保 QTextEdit 自动滚动到最后
        ui->textEdit_2->ensureCursorVisible();
    }
            );

    // 假设`serial`是你的QSerialPort对象的名称
    SendMessageThread *sendThread = new SendMessageThread(serial, ui,this);

    // 连接按钮点击事件的槽函数
    connect(ui->send, &QPushButton::clicked, sendThread, &SendMessageThread::sendMessage);
    // 连接按钮点击事件的槽函数
    connect(ui->send, &QPushButton::clicked, [=]() {
        if (!sendThread->isRunning()) {
             sendThread->start();
            qDebug() << "Thread started.";
        } else {
            qDebug() << "Thread is already running.";
        }
    });


    // 连接按钮点击事件的槽函数
        connect(sendThread, &SendMessageThread::messageSent, this, [=](const QString &message) {
            ui->textEdit_2->append(message); // 将消息追加到文本编辑器中
            ui->textEdit_2->ensureCursorVisible(); // 确保滚动到最后
        });









    // 清除TextEdit中的内容
    connect(ui->clearGet,&QPushButton::clicked,this, [=]()
            {
                // 清除TextEdit中的内容
                ui->textEdit->clear();
            }
            );

    //打开实时数据
    connect(ui->pushButton_OPenRealData,&QPushButton::clicked,this, [=]()
            {
                if(serial-> isOpen()){

                    QByteArray sendData;
                    // 在sendData的开头插入"W A001 U"
                    sendData.append("SHOW#\r\n");// 添加回车
                    serial->write(sendData);
                    ui->textEdit_2 -> append(sendData);
                    // 在添加新文本后，确保 QTextEdit 自动滚动到最后
                    ui->textEdit_2->ensureCursorVisible();
                }else
                {
                    ui->textEdit_2 -> append("ERROR: Serial port Close！\r");
                    // 在添加新文本后，确保 QTextEdit 自动滚动到最后
                    ui->textEdit_2->ensureCursorVisible();
                    // 处理文件无法打开的情况
                    QMessageBox::warning(this, tr("Error"), tr("请打开串口~"));
                }
            }
            );

    //关闭实时数据
    connect(ui->pushButton_ShutDownRealData,&QPushButton::clicked,this, [=]()
            {
                if(serial-> isOpen()){

                    QByteArray sendData;
                    // 在sendData的开头插入"W A001 U"
                    sendData.append("SHUT#\r\n");// 添加回车
                    serial->write(sendData);
                    ui->textEdit_2 -> append(sendData);
                    // 在添加新文本后，确保 QTextEdit 自动滚动到最后
                    ui->textEdit_2->ensureCursorVisible();
                }else
                {
                    ui->textEdit_2 -> append("ERROR: Serial port Close！\r");
                    // 在添加新文本后，确保 QTextEdit 自动滚动到最后
                    ui->textEdit_2->ensureCursorVisible();
                    QMessageBox::warning(this, tr("Error"), tr("请打开串口~"));
                }
            }
            );


    // 设置 QTextEdit 的样式表
    // ui->textEdit->setStyleSheet("QTextEdit textEdit { line-height: 5px; }");


    // 连接串口信号 readyRead 到槽函数 readData
    // 在类的构造函数或初始化函数中连接信号和槽
    connect(serial, &QSerialPort::readyRead, this, [=]() {
        QByteArray newData = serial->readAll(); // 读取新的数据

        // 将新的数据追加到已接收的数据中
        receivedData += newData;

        // 检查已接收的数据中是否包含完整的一行
        int lineEndIndex;
        while ((lineEndIndex = receivedData.indexOf("\r\n")) != -1) {
            // 如果找到完整的一行数据，提取并处理该行数据
            QString line = receivedData.left(lineEndIndex);
            receivedData = receivedData.mid(lineEndIndex + 2); // 移除已处理的数据

            // 保存当前光标位置
            QTextCursor cursor = ui->textEdit->textCursor();
            int position = cursor.position();

            // 获取光标在视图中的位置信息
            QScrollBar *vScrollBar = ui->textEdit->verticalScrollBar();
            int vScrollBarPos = vScrollBar->value();
            bool cursorAtEnd = (position == ui->textEdit->document()->characterCount() - 1); // 检查光标是否在最后一行

            // 将文本添加到末尾
            ui->textEdit->moveCursor(QTextCursor::End);
            ui->textEdit->insertPlainText(line + "\r\n");

            // 如果光标在末尾，将光标移动到末尾
            if (cursorAtEnd) {
                ui->textEdit->moveCursor(QTextCursor::End);
            } else {
                // 否则，恢复光标位置
                cursor.setPosition(position);
                ui->textEdit->setTextCursor(cursor);
            }

            // 如果滚动条在最下面，则将视图滚动到最后一行
            if (vScrollBar->value() == vScrollBar->maximum()) {
                vScrollBar->setValue(vScrollBar->maximum());
            } else {
                // 否则，恢复滚动条位置
                vScrollBar->setValue(vScrollBarPos);
            }

            // 确保光标可见
            ui->textEdit->ensureCursorVisible();







            // 调用解析函数解析数据
            QMap<QString, QString> parsedData = parseData(line, QStringList() << "AD" << "DTV"
             << "SV"<<"Vi"<<"Ii"<<"Pi"<<"AMP"<<"PF"<<"HJ"<<"PT"

                                                          );

            // 重新打印解析后的数据
            printParsedData(parsedData);
        }
    });

// //获取当前参数
     connect(ui->pushButton_getParameter, &QPushButton::clicked, this, [=]() {
    // 处理文件无法打开的情况
    QMessageBox::warning(this, tr("Error"), tr("还未开发！！！"));
         });


        //保存数据
        connect(ui->actionsave_data, &QAction::triggered, this, &MainWindow::saveTextEditToFile);

    // Only create new widgets if they don't exist yet
    if (!dataWidget_AD) {
        dataWidget_AD = new RealTimeDataWidget(this);  // Change parent to dialog
        dataWidget_AD->setYAxisLabel("AD");
        dataWidget_AD->hide();
    }
    if (!dataWidget_DTV) {
        dataWidget_DTV = new RealTimeDataWidget(this);  // Change parent to dialog
        dataWidget_DTV->setYAxisLabel("DTV");
        dataWidget_DTV->hide();
    }
    if (!dataWidget_Pi) {
        dataWidget_Pi = new RealTimeDataWidget(this);  // Change parent to dialog
        dataWidget_Pi->setYAxisLabel("Pi");
        dataWidget_Pi->hide();
    }
}

MainWindow::~MainWindow()
{
    delete ui;
    delete serial;
    delete dataWidget_AD;
    delete dataWidget_DTV;
    delete dataWidget_Pi;
}

// parseData 函数的实现
QMap<QString, QString> MainWindow::parseData(const QString &data, const QStringList &keys) {
    QMap<QString, QString> parsedData;

    // 使用正则表达式匹配键值对
    QRegularExpression regex("(\\b\\w+\\b)\\s*:\\s*(\\S+)"); // 匹配键和值，键是由单词字符组成的单词，值可以是任何非空白字符
    QRegularExpressionMatchIterator matchIterator = regex.globalMatch(data);

    // 遍历匹配结果
    while (matchIterator.hasNext()) {
        QRegularExpressionMatch match = matchIterator.next();
        if (match.hasMatch()) {
            QString key = match.captured(1); // 提取键
            QString value = match.captured(2); // 提取值
            if (keys.contains(key)) {
                parsedData[key] = value;
            }
        }
    }

    return parsedData;
}


void MainWindow::printParsedData(const QMap<QString, QString> &parsedData) {
    // 输出解析结果
    QMapIterator<QString, QString> i(parsedData);
    while (i.hasNext()) {
        i.next();
        //qDebug() << i.key() << ":" << i.value();
        // 将解析的数据传递给 RealTimePlotWidget
        bool ok;
        double value = i.value().toDouble(&ok);

        // 获取当前时间戳
        QDateTime currentTime = QDateTime::currentDateTime();
        double timestamp;
        // 如果是第一个数据点，记录下时间戳
        if (firstTimestamp.isNull()) {
            firstTimestamp = currentTime;
            timestamp = 0.0; // 第一个数据点的时间戳为 0
        } else {
            // 计算相对于第一个数据点的时间戳
            timestamp = firstTimestamp.msecsTo(currentTime) / 1000.0; // 毫秒转换为秒
        }

        if (ok && i.key() == "AD") {
            //qDebug() << value;
            // // 获取当前时间戳
            // QDateTime currentTime = QDateTime::currentDateTime();
            // double timestamp;
            // // 如果是第一个数据点，记录下时间戳
            // if (firstTimestamp.isNull()) {
            //     firstTimestamp = currentTime;
            //     timestamp = 0.0; // 第一个数据点的时间戳为 0
            // } else {
            //     // 计算相对于第一个数据点的时间戳
            //     timestamp = firstTimestamp.msecsTo(currentTime) / 1000.0; // 毫秒转换为秒
            // }
            dataWidget_AD->addDataPoint(timestamp, value);

        }

        if (ok && i.key() == "DTV") {
            // qDebug() << value;
            // // 获取当前时间戳
            // QDateTime currentTime = QDateTime::currentDateTime();
            // double timestamp;
            // // 如果是第一个数据点，记录下时间戳
            // if (firstTimestamp.isNull()) {
            //     firstTimestamp = currentTime;
            //     timestamp = 0.0; // 第一个数据点的时间戳为 0
            // } else {
            //     // 计算相对于第一个数据点的时间戳
            //     timestamp = firstTimestamp.msecsTo(currentTime) / 1000.0; // 毫秒转换为秒
            // }
            dataWidget_DTV->addDataPoint(timestamp, value);

        }

        if (ok && i.key() == "Pi") {
            // qDebug() << value;
            // // 获取当前时间戳
            // QDateTime currentTime = QDateTime::currentDateTime();
            // double timestamp;
            // // 如果是第一个数据点，记录下时间戳
            // if (firstTimestamp.isNull()) {
            //     firstTimestamp = currentTime;
            //     timestamp = 0.0; // 第一个数据点的时间戳为 0
            // } else {
            //     // 计算相对于第一个数据点的时间戳
            //     timestamp = firstTimestamp.msecsTo(currentTime) / 1000.0; // 毫秒转换为秒
            // }
            dataWidget_Pi->addDataPoint(timestamp, value);

        }
    }
}






void MainWindow::showForm()
{
    // 创建一个新的窗口对象
    QDialog *dialog = new QDialog(this); // 将this指针传递给QDialog的构造函数，使MainWindow成为其父对象

    // 使用 Uiloader 加载 UI 文件
    QUiLoader loader;
    //QString path = QDir::cleanPath(QCoreApplication::applicationDirPath() + QDir::separator() + QString("/form.ui"));
    QFile file(":form.ui"); // 替换成您的 UI 文件路径
    if (!file.open(QFile::ReadOnly)) {
        qDebug() << "Failed to open file:" << file.errorString();
        ui->textEdit_2 -> append("UI"+file.errorString()+"\r");
        // 在添加新文本后，确保 QTextEdit 自动滚动到最后
        ui->textEdit_2->ensureCursorVisible();
        // 处理文件无法打开的情况
        QMessageBox::warning(this, tr("Error"), tr("ui文件未找到！"));
        return;
    }
    QWidget *formWidget = loader.load(&file, dialog);
    file.close();

    // 如果加载成功，将表单添加到对话框中
    if (formWidget) {
        // 设置窗口标题
        dialog->setWindowTitle("绘图窗口");

        // 创建一个新的布局对象
        QVBoxLayout *layout = new QVBoxLayout(dialog);

        // // 创建一个实时数据窗口部件
        // dataWidget_AD = new RealTimeDataWidget(this);
        // //ui->verticalLayout_AD->addWidget(dataWidget_AD);
        // dataWidget_AD-> setYAxisLabel("AD");
        // dataWidget_DTV = new RealTimeDataWidget(this);
        // //ui->verticalLayout_DTV->addWidget(dataWidget_DTV);
        // dataWidget_DTV-> setYAxisLabel("DTV");




        // 将部件添加到布局中
        layout->addWidget(dataWidget_AD);
        layout->addWidget(dataWidget_DTV);
        layout->addWidget(dataWidget_Pi);
        dataWidget_AD->show();
        dataWidget_DTV->show();
        dataWidget_Pi->show();

        // 创建截图按钮
        QPushButton *screenshotButton = new QPushButton("截图", dialog);
        layout->addWidget(screenshotButton);


        // 将布局设置为对话框的布局
        dialog->setLayout(layout);


        // 设置截图按钮点击事件
        connect(screenshotButton, &QPushButton::clicked, [=]() {
            // 获取安装目录
            QString installDir = QCoreApplication::applicationDirPath();

            // 构造默认保存路径
            QString defaultPath = installDir + "/myimage";

            // 检查目标路径是否存在，如果不存在则创建
            QDir dir(defaultPath);
            if (!dir.exists()) {
                dir.mkpath(".");
            }

            // 构造默认文件名
            int count = 1;
            QString defaultFileName;
            do {
                defaultFileName = QString("image_%1.png").arg(count++);
            } while (QFile::exists(defaultPath + "/" + defaultFileName));

            // 打开文件保存对话框，让用户选择保存截图的文件名和路径
            QString filePath = QFileDialog::getSaveFileName(this, tr("Save Image"), defaultPath + "/" + defaultFileName, tr("Images (*.png)"));

            // 如果用户取消了选择，则返回
            if (filePath.isEmpty()) {
                return;
            }

            // 截取当前窗口并保存截图到指定路径
            QPixmap screenshot = dialog->grab();
            screenshot.save(filePath);

            // 显示保存路径的信息框
            QMessageBox::information(dialog, "截图成功", "已保存截图为 " + filePath);
        });




        // 设置窗口大小和位置
        dialog->resize(800, 800);
        dialog->move(100, 100);

        // 显示窗口
        dialog->show();
    } else {
        qDebug() << "Failed to load UI file:" << loader.errorString();
    }
}

//保存文本
void MainWindow::saveTextEditToFile() {
    // 获取安装目录
    QString installDir = QCoreApplication::applicationDirPath();

    // 构造默认保存路径
    QString defaultPath = installDir + "/myfile";

    // 创建保存文件的目标文件夹
    QDir dir(defaultPath);
    if (!dir.exists()) {
        if (!dir.mkpath(".")) {
            QMessageBox::warning(this, tr("Error"), tr("Failed to create directory."));
            return;
        }
    }

    // 打开文件保存对话框，让用户选择保存文件的路径，并设置默认路径
    QString filePath = QFileDialog::getSaveFileName(this, tr("Save File"), defaultPath, tr("Text Files (*.txt);;All Files (*)"));

    // 检查用户是否取消了文件保存对话框
    if (filePath.isEmpty()) {
        return;
    }

    // 获取 QTextEdit 中的文本内容
    QString text = ui->textEdit->toPlainText();

    // 打开文件（如果文件不存在则创建）
    QFile file(filePath);
    if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        QTextStream out(&file);
        out << text;
        file.close();

        // 显示保存路径的信息框
        QMessageBox::information(this, tr("Save Successful"), tr("File saved successfully at:\n%1").arg(filePath));
    } else {
        // 处理文件无法打开的情况
        QMessageBox::warning(this, tr("Error"), tr("Could not open file for writing."));
    }

}
